import serial
import serial.tools.list_ports
import sys
from typing import List, Tuple
from flask_socketio import SocketIO
import time  # 引入time模块用于耗时测量
import struct
import threading
import zq_data

selected_port = None
socket = None
is_serial_running = False
def list_serial_ports() -> List[Tuple[str, str]]:
    """列出所有可用串口并返回端口名和描述的元组列表"""
    ports = serial.tools.list_ports.comports()
    return [(port.device, port.description) for port in ports]

def ToggleSerialPort(is_running = False) -> None:
    global is_serial_running
    if is_running:
        is_serial_running = True
        log_handle = threading.Thread(target=log_thread, daemon=True)
        log_handle.start()
    else:
        is_serial_running = False






# 设备句柄
dev_handle = None
# 线程停止标志
thread_stop = threading.Event()
# 设备交互线程
dev_thread = None

def StartDev(dev_name:str):
    global dev_handle, dev_thread, thread_stop
    if dev_handle is not None:
        return dev_handle
    # 打开串口
    dev_handle = serial.Serial(
        port=dev_name,
        baudrate=115200,
        bytesize=serial.EIGHTBITS,      # 8位数据位
        parity=serial.PARITY_NONE,      # 无校验位
        stopbits=serial.STOPBITS_ONE,   # 1位停止位
        # timeout=0.01,                   # 读超时：立即返回
        timeout=0.001,                   # 读超时：立即返回
        write_timeout=0.2,              # 写超时：200ms
        xonxoff=False,                  # 禁用软件流控制
        rtscts=False,                   # 禁用RTS/CTS硬件流控制
        dsrdtr=False                    # 禁用DSR/DTR硬件流控制
    )
    # 显式禁用硬件流控制
    dev_handle.rts = False
    dev_handle.dtr = False

    # dev_handle = serial.Serial(dev_name, baudrate=115200, timeout=0.01, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE)
    if dev_handle is None:
        return None
    dev_thread = threading.Thread(target=log_thread, daemon=True)
    thread_stop.clear()
    dev_thread.start()

def StopDev() -> None:
    global dev_handle, dev_thread, thread_stop
    thread_stop.set()
    if dev_thread is not None:
        dev_thread.join()
        dev_thread = None
    if dev_handle is not None:
        dev_handle.close()
        dev_handle = None

def log_thread() -> None:
    global dev_handle, dev_thread, thread_stop, fota_recv_ack
    # while selected_port is None:
    #     time.sleep(0.05)        
    buf = bytearray()  # 缓冲区，用于暂存未完成的数据包
    log1 = log2 = ""
    """发送二进制命令并接收响应"""
    try:
        # 接收响应
        while not thread_stop.is_set():
            time.sleep(0.02)
            # 读取设备数据并扩展buf
            buf.extend(dev_handle.read(2048))
            # 处理接收数据
            buf, log1, log2 = zq_data.recv(buf, log1, log2)
            if len(log1) > 0:
                socket.emit('log1', {'data': log1})
                # 是否需要切换到高级log模式
                adv_cmd_pack = zq_data.get_log_switch_pack()
                if adv_cmd_pack:
                    try:
                        dev_handle.write(adv_cmd_pack)
                        dev_handle.flush()  # 强制刷新缓冲区确保数据发送
                    except serial.SerialTimeoutException: # 忽略写超时错误
                        pass    
                log1 = ""
            if len(log2) > 0:
                socket.emit('log2', {'data': log2})
                log2 = ""
            # 是否有OTA发送数据处理
            ota_pack = zq_data.get_ota_pack()
            if ota_pack:
                try:
                    dev_handle.write(ota_pack)
                    dev_handle.flush()  # 强制刷新缓冲区确保数据发送
                except serial.SerialTimeoutException: # 忽略写超时错误
                    pass    
    except Exception as e:
        print(f"串口操作错误: {e}")
    finally:
        dev_thread = None
        if dev_handle is not None:
            dev_handle.close()
            dev_handle = None

